package com.hzit.auth.config;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.hzit.auth.entity.R;
import com.hzit.auth.filter.TokenAuthFilter;
import com.hzit.auth.filter.TokenLoginFilter;
import com.hzit.auth.security.TokenLogoutHandler;
import com.hzit.auth.security.TokenManager;
import com.hzit.auth.util.ResponseUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.WebSecurityConfigurer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.access.AccessDeniedHandler;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;



/**
 * 类名：
 * 作者：WF
 * 功能：
 */
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class HzitSecurityConfig extends WebSecurityConfigurerAdapter {
	private TokenManager tokenManager;
	private RedisTemplate redisTemplate;
	private UserDetailsService userDetailsService;

	@Autowired
	public HzitSecurityConfig(UserDetailsService userDetailsService,
	                              TokenManager tokenManager,
	                             RedisTemplate redisTemplate) {
		this.userDetailsService = userDetailsService;
		this.tokenManager = tokenManager;
		this.redisTemplate = redisTemplate;
	}
	@Override
	protected void configure(HttpSecurity http) throws Exception {
		http.exceptionHandling()
				 .authenticationEntryPoint((request, response, authException) -> {   // 认证失败处理器
				 	response.setContentType("text/json;charset=utf-8");
				 	R r = R.error().code(401).message("对不起，未登录！");
				 	ResponseUtil.out(response,r);
				 })
				.accessDeniedHandler((request, response, ex) -> {                   // 授权失败处理器
					response.setContentType("text/json;charset=utf-8");
					R  r = R.error().code(403).message("对不起，无权访问！");
					ResponseUtil.out(response,r);
				});

		http.csrf().disable()

			.authorizeRequests()
			// .antMatchers("/login.html","/webjars/**").permitAll()

			.anyRequest().authenticated()

			.and().logout().logoutUrl("/admin/acl/index/logout")//退出路径
			.addLogoutHandler(new TokenLogoutHandler(tokenManager,redisTemplate)).and()
			// 添加认证过滤器
			.addFilter(new TokenLoginFilter(authenticationManager(), tokenManager, redisTemplate))
			// 添加授权过滤器
			.addFilter(new TokenAuthFilter(authenticationManager(), tokenManager, redisTemplate)).httpBasic();

	}
	//调用userDetailsService和密码处理
	@Override
	public void configure(AuthenticationManagerBuilder auth) throws Exception {
		auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
	}
	@Bean
	public BCryptPasswordEncoder passwordEncoder(){
		return new BCryptPasswordEncoder();
	}
	//不进行认证的路径，可以直接访问
	@Override
	public void configure(WebSecurity web) throws Exception {
		web.ignoring().antMatchers("/login.html","/webjars/**","/user/findByUsername/*","/user/findPermissionListByUserId/*");
	}


}
